
#ifndef _TTG_PIPELINE_SUB_PIPELINE_
#define _TTG_PIPELINE_SUB_PIPELINE_
#include "Common/Definitions.h"

#include "Common/Structures.h"
#include "Nodes/StandartNodes.h"
#include "ISubPipeline.h"
#include "BasicPipeline.h"

namespace ttg_internal
{
	namespace pipeline
	{
		//Contains implementation of additional subpipeline.
		template <class InType, class OutType>
		class SubPipeline :public BasicPipeline<InType, OutType,
												StartOfSubPipeline<InType>,
												EndOfSubPipeline<OutType>>,
						   public ISubPipeline
		{
			private:
				ttg::utils::ParameterSet *filter;
				void clearInputData(std::vector<OutType> *data)
				{
					getIContext().getPipelineContext().clearInputData(
						getIContext().getDataBuffer().getContextID());
				}
			protected:
				//ISubPipeline member. Starts pipeline and returns ID of the used context.
				virtual void start(void *data, void *d)
				{
					//Remapping.
					ttg::structures::Enumerator<InType> &_data
						= *(ttg::structures::Enumerator<InType> *)data;
					ttg::structures::Delegate<void, std::vector<OutType> *> *_d
						= (ttg::structures::Delegate<void, std::vector<OutType> *> *)d;
					//Launching.
					ttg::pipeline::ContextID ID = 
						getIContext().getContextIDManager().createContextID();
					getIContext().getPipelineContext().setInputData(ID, _data);
					startIteration(_data, ID);
					getManager().getPipelineEnd().onFinish(ID) += _d;
					getManager().getPipelineEnd().onFinish(ID)
						+= ttg::structures::make_delegate(this, &SubPipeline<InType, OutType>::clearInputData);
					finishIteration(ID);
				}
			public:
				//Creates required subpipeline and adds himself to "sub_pipelines".
				inline SubPipeline(ttg::pipeline::NodeWrapper<InType, OutType> &wrapper,
								   const char *name,
								   ttg::structures::Dictionary<ISubPipeline> *sub_pipelines,
								   ttg::utils::ParameterSet *root_filter)
					:BasicPipeline<InType, OutType,
								   StartOfSubPipeline<InType>,
								   EndOfSubPipeline<OutType>>(wrapper, name),
				     ISubPipeline(name, typeid(InType).name(), typeid(OutType).name())
				{
					//Creating filter for nodes and binding them.
					filter = new ttg::utils::ParameterSet(name, root_filter);
					std::vector<NavigatorNode *> &en = getManager().getNodes();
					for (size_t i = 0; i < en.size(); i++)
						en[i]->getInfo().bind(filter);
					//Registering sub_pipelines.
					getIContext().setSubPipelines(sub_pipelines);
					sub_pipelines->add(this);
				}
				virtual void setUserContext(ttg::pipeline::UserContext *context)
				{
					getIContext().getPipelineContext().setUserContext(context);
				}
		};
	}
}

#endif
